/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define private public
#define protected public
#include "ime_cfg_manager.h"
#include "ime_info_inquirer.h"
#include "sys_cfg_parser.h"
#undef private

#include <gtest/gtest.h>
#include <unistd.h>

#include "parameters.h"

using namespace testing;
using namespace testing::ext;
namespace OHOS {
namespace MiscServices {
class JsonOperateTest : public testing::Test {
public:
    static constexpr const char *IME_PERSIST_CFG = "{\"imeCfgList\":[{\"userId\":100,\"currentIme\":\"bundleName/"
                                                   "extName\",\"currentSubName\":\"subName\",\"tempScreenLockIme\":"
                                                   "\"\",\"isDefaultImeSet\":false},{\"userId\":104,\"currentIme\":"
                                                   "\"bundleName1/"
                                                   "extName1\",\"currentSubName\":\"subName1\",\"tempScreenLockIme\":"
                                                   "\"\",\"isDefaultImeSet\":false}]}";
    static constexpr const char *IME_PERSIST_CFG_NULL = "{\"imeCfgList\":[]}";
    static constexpr const char *IME_PERSIST_CFG_VALUE_TYPE_ERROR = "{\"imeCfgList\":[{\"userId\":100,\"currentIme\":"
                                                                    "\"bundleName/"
                                                                    "extName\",\"currentSubName\":\"subName\"},{"
                                                                    "\"userId\":"
                                                                    "\"104\",\"currentIme\":\"bundleName1/"
                                                                    "extName1\",\"currentSubName\":\"subName1\"}]}";
    static constexpr const char *IME_PERSIST_CFG_NAME_LACK = "{\"imeCfgList\":[{\"userId\":100,\"currentSubName\":"
                                                             "\"subName\"}]}";
    static constexpr const char *IME_PERSIST_CFG_NAME_ERROR = "{\"imeCfgList\":[{\"userId\":100, \"bundle\": "
                                                              "\"bundleName/extNme\",\"currentSubName\":"
                                                              "\"subName\"}]}";

    static constexpr const char *ENABLE_IME = "{\"enableImeList\" : {\"100\" : [ \"testIme\", \"testIme1\", "
                                              "\"testIme2\"],\"101\" : [\"testIme3\"], \"102\" : []}}";
    static constexpr const char *ENABLE_KEYBOARD = "{\"enableKeyboardList\" : {\"100\" : [ \"testKeyboard\", "
                                                   "\"testKeyboard1\"],\"101\" : "
                                                   "[\"testKeyboard2\"], \"105\" : []}}";
    static constexpr const char *SECURITY_MODE = "{\"fullExperienceList\" : {\"100\" : [\"testIme\", "
                                                 "\"testIme3\"], \"102\" : []}}";
    static constexpr const char *SUBTYPE = "{\"subtypes\": [{\"icon\": \"$media:icon\",\"id\": "
                                           "\"subtypeId\",\"label\": \"$string:chinese\",\"locale\": "
                                           "\"zh-CN\",\"mode\": \"lower\"},{\"icon\": \"$media:icon1\",\"id\": "
                                           "\"subtypeId1\",\"label\": \"$string:english\",\"locale\": "
                                           "\"en-US\",\"mode\": \"upper\"}]} ";
    static constexpr const char *INPUT_SYS_CGF = "{\"systemConfig\":{\"enableInputMethodFeature\":true,"
                                                 "\"enableFullExperienceFeature\":true,"
                                                 "\"systemInputMethodConfigAbility\":\"setAbility\","
                                                 "\"defaultInputMethod\":\"bundleName/extName\","
                                                 "\"systemSpecialInputMethod\":\"systemSpecialInputMethod\"}, "
                                                 "\"supportedInputTypeList\":[{\"inputType\":0,\"bundleName\":"
                                                 "\"testBundleName\", "
                                                 "\"subtypeId\":\"testSubtypeId\"},{\"inputType\":1,\"bundleName\":"
                                                 "\"\", \"subtypeId\":\"\"}]}";
    static constexpr const char *SYS_PANEL_ADJUST = "{\"sysPanelAdjust\":"
                                                    "[{\"style\": [\"fix\",\"default\",\"landscape\"],"
                                                    "\"top\": 1,\"left\": 2,\"right\": 3,\"bottom\": 4}]}";
    static constexpr const char *IGNORE_SYS_PANEL_ADJUST = "{\"ignoreSysPanelAdjust\":{\"inputType\": [0, 1, 3]}}";
    static constexpr const char *INPUT_SYS_CGF_UID_LIST = "{\"systemConfig\": {\"proxyImeUidList\": [7101, 5521]}}";
    static void SetUpTestCase() { }
    static void TearDownTestCase() { }
    void SetUp() { }
    void TearDown()
    {
        ClearTestParameters();
    }
    // Helper function: Set system parameter
    void SetSystemParameter(const std::string &key, const std::string &value)
    {
        system::SetParameter(key, value);
        testParameters_.push_back(key);
    }

    // Helper function: Clear test parameters
    void ClearTestParameters()
    {
        for (const auto &param : testParameters_) {
            system::SetParameter(param, "");
        }
        testParameters_.clear();
    }
    std::vector<std::string> testParameters_; // Tracks parameter keys set during testing
};

/**
 * @tc.name: testParseImePersistCfg001
 * @tc.desc: parse imePersistCfg
 * @tc.type: FUNC
 * @tc.require:
 * @tc.author: chenyu
 */
HWTEST_F(JsonOperateTest, testParseImePersistCfg001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseImePersistCfg001 START");
    ImeCfgManager::GetInstance().imeConfigs_.clear();
    auto ret = ImeCfgManager::GetInstance().ParseImeCfg(JsonOperateTest::IME_PERSIST_CFG);
    ASSERT_TRUE(ret);
    ASSERT_EQ(ImeCfgManager::GetInstance().imeConfigs_.size(), 2);
    auto cfg = ImeCfgManager::GetInstance().imeConfigs_;
    EXPECT_EQ(cfg[0].userId, 100);
    EXPECT_EQ(cfg[0].currentIme, "bundleName/extName");
    EXPECT_EQ(cfg[0].currentSubName, "subName");
    EXPECT_EQ(cfg[1].userId, 104);
    EXPECT_EQ(cfg[1].currentIme, "bundleName1/extName1");
    EXPECT_EQ(cfg[1].currentSubName, "subName1");

    ImeCfgManager::GetInstance().imeConfigs_.clear();
    ret = ImeCfgManager::GetInstance().ParseImeCfg(JsonOperateTest::IME_PERSIST_CFG_NULL);
    EXPECT_TRUE(ret);
    EXPECT_TRUE(ImeCfgManager::GetInstance().imeConfigs_.empty());

    ImeCfgManager::GetInstance().imeConfigs_.clear();
    ret = ImeCfgManager::GetInstance().ParseImeCfg(JsonOperateTest::IME_PERSIST_CFG_VALUE_TYPE_ERROR);
    EXPECT_FALSE(ret);
    EXPECT_TRUE(ImeCfgManager::GetInstance().imeConfigs_.empty());

    ImeCfgManager::GetInstance().imeConfigs_.clear();
    ret = ImeCfgManager::GetInstance().ParseImeCfg(JsonOperateTest::IME_PERSIST_CFG_NAME_LACK);
    EXPECT_FALSE(ret);
    EXPECT_TRUE(ImeCfgManager::GetInstance().imeConfigs_.empty());

    ImeCfgManager::GetInstance().imeConfigs_.clear();
    ret = ImeCfgManager::GetInstance().ParseImeCfg(JsonOperateTest::IME_PERSIST_CFG_NAME_ERROR);
    EXPECT_FALSE(ret);
    EXPECT_TRUE(ImeCfgManager::GetInstance().imeConfigs_.empty());

    ret = ImeCfgManager::GetInstance().ParseImeCfg(JsonOperateTest::ENABLE_KEYBOARD);
    EXPECT_FALSE(ret);
}

/**
 * @tc.name: testPackageImePersistCfg001
 * @tc.desc: package imePersistCfg
 * @tc.type: FUNC
 * @tc.require:
 * @tc.author: chenyu
 */
HWTEST_F(JsonOperateTest, testPackageImePersistCfg001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testPackageImePersistCfg001 START");
    ImeCfgManager::GetInstance().imeConfigs_.clear();
    ImeCfgManager::GetInstance().imeConfigs_.emplace_back(100, "bundleName/extName", "subName", false);
    ImeCfgManager::GetInstance().imeConfigs_.emplace_back(104, "bundleName1/extName1", "subName1", false);
    auto str = ImeCfgManager::GetInstance().PackageImeCfg();
    EXPECT_EQ(str, JsonOperateTest::IME_PERSIST_CFG);
}

/**
 * @tc.name: testParseSystemConfig001
 * @tc.desc: parse systemConfig
 * @tc.type: FUNC
 * @tc.require:
 * @tc.author: chenyu
 */
HWTEST_F(JsonOperateTest, testParseSystemConfig001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseSystemConfig001 START");
    ImeSystemConfig imeSystemConfig;
    auto ret = imeSystemConfig.Unmarshall(INPUT_SYS_CGF);
    ASSERT_TRUE(ret);
    auto systemConfig = imeSystemConfig.systemConfig;
    EXPECT_EQ(systemConfig.systemInputMethodConfigAbility, "setAbility");
    EXPECT_EQ(systemConfig.defaultInputMethod, "bundleName/extName");
    EXPECT_EQ(systemConfig.systemSpecialInputMethod, "systemSpecialInputMethod");
    EXPECT_TRUE(systemConfig.enableInputMethodFeature);
    EXPECT_TRUE(systemConfig.enableFullExperienceFeature);
}

/**
 * @tc.name: testParseInputType001
 * @tc.desc: parse inputType
 * @tc.type: FUNC
 * @tc.require:
 * @tc.author: chenyu
 */
HWTEST_F(JsonOperateTest, testParseInputType001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseInputType001 START");
    InputTypeCfg inputTypeCfg;
    auto ret = inputTypeCfg.Unmarshall(INPUT_SYS_CGF);
    ASSERT_TRUE(ret);
    auto inputType = inputTypeCfg.inputType;
    ASSERT_EQ(inputType.size(), 2);
    EXPECT_EQ(inputType[0].type, InputType::CAMERA_INPUT);
    EXPECT_EQ(inputType[0].subName, "testSubtypeId");
    EXPECT_EQ(inputType[0].bundleName, "testBundleName");
    EXPECT_EQ(inputType[1].type, InputType::SECURITY_INPUT);
    EXPECT_EQ(inputType[1].subName, "");
    EXPECT_EQ(inputType[1].bundleName, "");
}

/**
 * @tc.name: testParseSubtype001
 * @tc.desc: parse subtype
 * @tc.type: FUNC
 * @tc.require:
 * @tc.author: chenyu
 */
HWTEST_F(JsonOperateTest, testParseSubtype001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseSubtype001 START");
    std::vector<std::string> profiles { { JsonOperateTest::SUBTYPE } };
    SubtypeCfg subtype;
    auto ret = ImeInfoInquirer::GetInstance().ParseSubtypeProfile(profiles, subtype);
    ASSERT_TRUE(ret);
    ASSERT_EQ(subtype.subtypes.size(), 2);
    auto subtypes = subtype.subtypes;
    EXPECT_EQ(subtypes[0].icon, "$media:icon");
    EXPECT_EQ(subtypes[0].id, "subtypeId");
    EXPECT_EQ(subtypes[0].label, "$string:chinese");
    EXPECT_EQ(subtypes[0].locale, "zh-CN");
    EXPECT_EQ(subtypes[0].mode, "lower");
    EXPECT_EQ(subtypes[1].icon, "$media:icon1");
    EXPECT_EQ(subtypes[1].id, "subtypeId1");
    EXPECT_EQ(subtypes[1].label, "$string:english");
    EXPECT_EQ(subtypes[1].locale, "en-US");
    EXPECT_EQ(subtypes[1].mode, "upper");

    std::vector<std::string> profiles1 { { JsonOperateTest::SECURITY_MODE } };
    SubtypeCfg subtype1;
    ret = ImeInfoInquirer::GetInstance().ParseSubtypeProfile(profiles1, subtype1);
    EXPECT_FALSE(ret);
    EXPECT_TRUE(subtype1.subtypes.empty());
}

/**
 * @tc.name: testParseSysPanelAdjust001
 * @tc.desc: parse SysPanelAdjust
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testParseSysPanelAdjust001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseSysPanelAdjust001 START");
    SysPanelAdjustCfg sysPanelAdjustCfg;
    auto ret = sysPanelAdjustCfg.Unmarshall(SYS_PANEL_ADJUST);
    ASSERT_TRUE(ret);
    auto panelAdjust = sysPanelAdjustCfg.panelAdjust;
    EXPECT_EQ(panelAdjust[0].style[0], "fix");
    EXPECT_EQ(panelAdjust[0].style[1], "default");
    EXPECT_EQ(panelAdjust[0].style[2], "landscape");
    EXPECT_EQ(panelAdjust[0].top, 1);
    EXPECT_EQ(panelAdjust[0].left, 2);
    EXPECT_EQ(panelAdjust[0].right, 3);
    EXPECT_EQ(panelAdjust[0].bottom, 4);
}

/**
@tc.name: testParseIgnoreSysPanelAdjust001
@tc.desc: parse IgnoreSysPanelAdjust
@tc.type: FUNC
@tc.require:
*/
HWTEST_F(JsonOperateTest, testParseIgnoreSysPanelAdjust001, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseIgnoreSysPanelAdjust001 START");
    IgnoreSysPanelAdjustCfg ignoreSysPanelAdjustCfg;
    auto ret = ignoreSysPanelAdjustCfg.Unmarshall("");
    ASSERT_FALSE(ret);
}

/**
@tc.name: testParseIgnoreSysPanelAdjust002
@tc.desc: parse IgnoreSysPanelAdjust
@tc.type: FUNC
@tc.require:
*/
HWTEST_F(JsonOperateTest, testParseIgnoreSysPanelAdjust002, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseIgnoreSysPanelAdjust002 START");
    IgnoreSysPanelAdjustCfg ignoreSysPanelAdjustCfg;
    auto ret = ignoreSysPanelAdjustCfg.Unmarshall(IGNORE_SYS_PANEL_ADJUST);
    ASSERT_TRUE(ret);
    auto ignoreSysPanelAdjust = ignoreSysPanelAdjustCfg.ignoreSysPanelAdjust;
    EXPECT_EQ(ignoreSysPanelAdjust.inputType[0], 0);
    EXPECT_EQ(ignoreSysPanelAdjust.inputType[1], 1);
    EXPECT_EQ(ignoreSysPanelAdjust.inputType[2], 3);
}

/**
 * @tc.name: testGetDumpInfo
 * @tc.desc: parse GetDumpInfo
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testGetDumpInfo, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testGetDumpInfo START");
    int32_t userId = 1234567890;
    auto ret = ImeInfoInquirer::GetInstance().GetDumpInfo(userId);
    ASSERT_EQ(ret, "");
}

/**
 * @tc.name: testListDisabledInputMethod
 * @tc.desc: ListDisabledInputMethod
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testListDisabledInputMethod, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testListDisabledInputMethod START");
    int32_t userId = 1234567890;
    std::vector<Property> props;
    auto ret = ImeInfoInquirer::GetInstance().ListDisabledInputMethod(userId, props);
    ASSERT_NE(ret, ErrorCode::NO_ERROR);
    ret = ImeInfoInquirer::GetInstance().ListDisabledInputMethod(userId, props);
    ASSERT_NE(ret, ErrorCode::NO_ERROR);
}

/**
 * @tc.name: testGetSwitchInfoBySwitchCount
 * @tc.desc: test GetSwitchInfoBySwitchCount
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testGetSwitchInfoBySwitchCount, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testGetSwitchInfoBySwitchCount START");
    SwitchInfo switchInfo;
    uint32_t cacheCount = 987654321;
    int32_t userId = 1234567890;
    auto ret = ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(switchInfo, userId, cacheCount);
    ASSERT_NE(ret, ErrorCode::NO_ERROR);
}

/**
 * @tc.name: testGetInputMethodConfig
 * @tc.desc: test GetInputMethodConfig
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testGetInputMethodConfig, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testGetInputMethodConfig START");
    AppExecFwk::ElementName inputMethodConfig;
    int32_t userId = 100;
    auto ret = ImeInfoInquirer::GetInstance().GetInputMethodConfig(userId, inputMethodConfig);
    ASSERT_EQ(ret, ErrorCode::NO_ERROR);
}

/**
 * @tc.name: testFindTargetSubtypeByCondition
 * @tc.desc: test FindTargetSubtypeByCondition
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testFindTargetSubtypeByCondition, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testFindTargetSubtypeByCondition START");
    std::vector<SubProperty> subProps;
    Condition condition = Condition::ENGLISH;
    auto ret = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(subProps, condition);
    ASSERT_EQ(ret, nullptr);
    int32_t invalidNum = 5;
    condition = static_cast<Condition>(invalidNum);
    ret = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(subProps, condition);
    ASSERT_EQ(ret, nullptr);
}

/**
 * @tc.name: testParseSubtypeProfile
 * @tc.desc: test ParseSubtypeProfile
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testParseSubtypeProfile, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseSubtypeProfile START");
    std::vector<std::string> profiles;
    SubtypeCfg subtypeCfg;
    auto ret = ImeInfoInquirer::GetInstance().ParseSubtypeProfile(profiles, subtypeCfg);
    ASSERT_FALSE(ret);
}

/**
 * @tc.name: testGetResMgr
 * @tc.desc: test GetResMgr
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, testGetResMgr, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testGetResMgr START");
    std::string resourcePath = "";
    auto ret = ImeInfoInquirer::GetInstance().GetResMgr(resourcePath);
    ASSERT_FALSE(ret);
}

/**
 * @tc.name: IsDynamicStartIme_EmptyDynamicList_ReturnFalse
 * @tc.desc: Verify IsDynamicStartIme() returns false when dynamic start list is empty
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, IsDynamicStartIme_EmptyDynamicList_ReturnFalse, TestSize.Level0)
{
    // Preparation: Set empty dynamic start configuration list
    auto instance = ImeInfoInquirer::GetInstance();
    instance.dynamicStartImeList_ = {};

    // Execution
    bool result = instance.IsDynamicStartIme();

    // Verification
    EXPECT_FALSE(result);
}

/**
 * @tc.name: IsDynamicStartIme_NoMatchingParameter_ReturnFalse
 * @tc.desc: Verify IsDynamicStartIme() returns false when no matching system parameter exists
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, IsDynamicStartIme_NoMatchingParameter_ReturnFalse, TestSize.Level0)
{
    // Preparation: Configuration list contains one rule
    auto instance = ImeInfoInquirer::GetInstance();
    instance.InitDynamicStartImeCfg();
    std::vector<DynamicStartImeCfgItem> testList = {
        { "ime.dynamic.start", "true" }
    };
    instance.dynamicStartImeList_ = testList;

    // Set non-matching system parameter
    SetSystemParameter("ime.dynamic.start", "false");

    // Execution
    bool result = instance.IsDynamicStartIme();

    // Verification
    EXPECT_FALSE(result);
}

/**
 * @tc.name: IsDynamicStartIme_OneMatchingParameter_ReturnTrue
 * @tc.desc: Verify IsDynamicStartIme() returns true when there's one matching parameter
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, IsDynamicStartIme_OneMatchingParameter_ReturnTrue, TestSize.Level0)
{
    // Preparation: Configuration list contains one matching rule
    auto instance = ImeInfoInquirer::GetInstance();
    instance.dynamicStartImeList_ = {
        { "ime.enable.dynamic", "1" }
    };

    // Set matching system parameter
    SetSystemParameter("ime.enable.dynamic", "1");

    // Execution
    bool result = instance.IsDynamicStartIme();

    // Verification
    EXPECT_TRUE(result);
}

/**
 * @tc.name: IsDynamicStartIme_MultiRulesOneMatching_ReturnTrue
 * @tc.desc: Verify IsDynamicStartIme() returns true when one of multiple rules matches
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, IsDynamicStartIme_MultiRulesOneMatching_ReturnTrue, TestSize.Level0)
{
    // Preparation: Configuration list contains multiple rules
    auto instance = ImeInfoInquirer::GetInstance();
    instance.dynamicStartImeList_ = {
        { "ime.condition1", "ok"  }, // No match
        { "ime.condition2", "yes" }  // Match
    };

    // Set system parameters
    SetSystemParameter("ime.condition1", "no");
    SetSystemParameter("ime.condition2", "yes");

    // Execution
    bool result = instance.IsDynamicStartIme();

    // Verification
    EXPECT_TRUE(result);
}

/**
 * @tc.name: IsDynamicStartIme_EmptyValueMatch_ReturnTrue
 * @tc.desc: Verify IsDynamicStartIme() returns true when empty values match
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, IsDynamicStartIme_EmptyValueMatch_ReturnTrue, TestSize.Level0)
{
    // Preparation: Configuration rule contains empty value
    auto instance = ImeInfoInquirer::GetInstance();
    instance.dynamicStartImeList_ = {
        { "ime.empty.value", "" }
    };

    // Set empty string system parameter (matching)
    SetSystemParameter("ime.empty.value", "");

    // Execution
    bool result = instance.IsDynamicStartIme();

    // Verification
    EXPECT_TRUE(result);
}

/**
 * @tc.name: DynamicStartImeUnmarshal_NormalCase_MultiEntries
 * @tc.desc: DynamicStartImeUnmarshal_NormalCase_MultiEntries
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, DynamicStartImeUnmarshal_NormalCase_MultiEntries, TestSize.Level0)
{
    const std::string jsonStr = R"(
        {
            "dynamicStartImeCfgList": [
                { "sysParam": "param1", "value": "value1" },
                { "sysParam": "param2", "value": "value2" }
            ]
        }
    )";
    cJSON *node = cJSON_Parse(jsonStr.c_str());
    ASSERT_NE(node, nullptr) << "JSON parse failed.";

    DynamicStartImeCfg cfg;
    bool ret = cfg.Unmarshal(node);

    EXPECT_TRUE(ret);
    EXPECT_EQ(cfg.dynamicStartImeCfgList.size(), 2);
    EXPECT_EQ(cfg.dynamicStartImeCfgList[0].sysParam, "param1");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[0].value, "value1");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[1].sysParam, "param2");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[1].value, "value2");
    cJSON_Delete(node);
}

/**
 * @tc.name: DynamicStartImeUnmarshal_NormalCase_EmptyList
 * @tc.desc: DynamicStartImeUnmarshal_NormalCase_EmptyList
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, DynamicStartImeUnmarshal_NormalCase_EmptyList, TestSize.Level0)
{
    const std::string jsonStr = R"(
        {
            "dynamicStartImeCfgList": []
        }
    )";
    cJSON *node = cJSON_Parse(jsonStr.c_str());
    ASSERT_NE(node, nullptr) << "JSON parse failed.";

    DynamicStartImeCfg cfg;
    bool ret = cfg.Unmarshal(node);

    EXPECT_TRUE(ret);
    EXPECT_TRUE(cfg.dynamicStartImeCfgList.empty());

    cJSON_Delete(node);
}

/**
 * @tc.name: DynamicStartImeUnmarshal_AbnormalCase_MissingField
 * @tc.desc: DynamicStartImeUnmarshal_AbnormalCase_MissingField
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, DynamicStartImeUnmarshal_AbnormalCase_MissingField, TestSize.Level0)
{
    const std::string jsonStr = R"(
        {
            "otherField": "test"
        }
    )";
    cJSON *node = cJSON_Parse(jsonStr.c_str());
    ASSERT_NE(node, nullptr) << "JSON parse failed.";

    DynamicStartImeCfg cfg;
    bool ret = cfg.Unmarshal(node);

    EXPECT_FALSE(ret);
    EXPECT_TRUE(cfg.dynamicStartImeCfgList.empty());

    cJSON_Delete(node);
}

/**
 * @tc.name: DynamicStartImeUnmarshal_AbnormalCase_InvalidType
 * @tc.desc: DynamicStartImeUnmarshal_AbnormalCase_InvalidType
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, DynamicStartImeUnmarshal_AbnormalCase_InvalidType, TestSize.Level0)
{
    const std::string jsonStr = R"(
        {
            "dynamicStartImeCfgList": "not an array"
        }
    )";
    cJSON *node = cJSON_Parse(jsonStr.c_str());
    ASSERT_NE(node, nullptr) << "JSON parse failed.";

    DynamicStartImeCfg cfg;
    bool ret = cfg.Unmarshal(node);

    EXPECT_FALSE(ret);
    EXPECT_TRUE(cfg.dynamicStartImeCfgList.empty());

    cJSON_Delete(node);
}

/**
 * @tc.name: DynamicStartImeUnmarshal_AbnormalCase_InvalidEntry
 * @tc.desc: DynamicStartImeUnmarshal_AbnormalCase_InvalidEntry
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, DynamicStartImeUnmarshal_AbnormalCase_InvalidEntry, TestSize.Level0)
{
    const std::string jsonStr = R"(
        {
            "dynamicStartImeCfgList": [
                { "sysParam": "param1", "value": "value1" },
                { "sysParam": "param2" }
            ]
        }
    )";
    cJSON *node = cJSON_Parse(jsonStr.c_str());
    ASSERT_NE(node, nullptr) << "JSON parse failed.";

    DynamicStartImeCfg cfg;
    bool ret = cfg.Unmarshal(node);

    EXPECT_FALSE(ret);
    EXPECT_EQ(cfg.dynamicStartImeCfgList.size(), 2);
    EXPECT_EQ(cfg.dynamicStartImeCfgList[0].sysParam, "param1");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[0].value, "value1");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[1].sysParam, "param2");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[1].value, "");
    cJSON_Delete(node);
}

/**
 * @tc.name: DynamicStartImeUnmarshal_BoundaryCase_EmptyValues
 * @tc.desc: DynamicStartImeUnmarshal_BoundaryCase_EmptyValues
 * @tc.type: FUNC
 * @tc.require:
 */
HWTEST_F(JsonOperateTest, DynamicStartImeUnmarshal_BoundaryCase_EmptyValues, TestSize.Level0)
{
    const std::string jsonStr = R"(
        {
            "dynamicStartImeCfgList": [
                { "sysParam": "", "value": "" },
                { "sysParam": "", "value": "value2" }
            ]
        }
    )";
    cJSON *node = cJSON_Parse(jsonStr.c_str());
    ASSERT_NE(node, nullptr) << "JSON parse failed.";

    DynamicStartImeCfg cfg;
    bool ret = cfg.Unmarshal(node);

    EXPECT_TRUE(ret);
    EXPECT_EQ(cfg.dynamicStartImeCfgList.size(), 2);
    EXPECT_EQ(cfg.dynamicStartImeCfgList[0].sysParam, "");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[0].value, "");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[1].sysParam, "");
    EXPECT_EQ(cfg.dynamicStartImeCfgList[1].value, "value2");

    cJSON_Delete(node);
}

/**
 * @tc.name: testParseSystemConfigUidList
 * @tc.desc: parse systemConfig
 * @tc.type: FUNC
 * @tc.require:
 * @tc.author: chenyu
 */
HWTEST_F(JsonOperateTest, testParseSystemConfigUidList, TestSize.Level1)
{
    IMSA_HILOGI("JsonOperateTest testParseSystemConfigUidList START");
    ImeSystemConfig imeSystemConfig;
    auto ret = imeSystemConfig.Unmarshall(INPUT_SYS_CGF_UID_LIST);
    ASSERT_TRUE(ret);
    auto systemConfig = imeSystemConfig.systemConfig;
    int32_t uid = 0;
    EXPECT_FALSE(systemConfig.proxyImeUidList.find(uid) != systemConfig.proxyImeUidList.end());
    uid = 7101;
    EXPECT_TRUE(systemConfig.proxyImeUidList.find(uid) != systemConfig.proxyImeUidList.end());
    uid = 5521;
    EXPECT_TRUE(systemConfig.proxyImeUidList.find(uid) != systemConfig.proxyImeUidList.end());
}
} // namespace MiscServices
} // namespace OHOS